package se.perp.c4.model;

import java.util.LinkedList;
import java.util.List;
import se.perp.c4.model.Actor.EActor;

public class Territory {

    public enum ETerritory {
        NOWHERE,
        SHIRE, ARTHEDAIN, CARDOLAN, RHUDAUR, EREGION, ENEDWAITH,
        HIGHPASS, MISTYMTS, MORIA, GAPOFROHAN,
        MIRKWOOD, FANGORN, ROHAN, DAGORLAD, GONDOR, MORDOR
    };

    public enum Type {

        HOME, NORMAL, MOUNTAIN
    };
    public ETerritory[] lightNeighbors = new ETerritory[0];
    public ETerritory[] darkNeighbors = new ETerritory[0];
    public ETerritory[] sidewaysNeighbors = new ETerritory[0];
    public ETerritory[] adjacent = new ETerritory[0];
    public int capacity;
    public ETerritory which;
    public Type type;
    private List<Actor> occupants = new LinkedList<Actor>();

    public List<Actor> getOccupants() {
        return occupants;
    }

    public boolean isFull() {
        return occupants.size() == capacity;
    }

    public boolean addActor(Actor a) {
        if (occupants.size() < capacity) {
            occupants.add(a);
            a.where = this.which;
            return true;
        }
        return false;
    }

    public boolean hasLightNeighbor(ETerritory eid) {
        for (ETerritory e : lightNeighbors) {
            if (e == eid) {
                return true;
            }
        }
        return false;
    }

    public boolean hasDarkNeighbor(ETerritory eid) {
        for (ETerritory e : darkNeighbors) {
            if (e == eid) {
                return true;
            }
        }
        return false;
    }

    public boolean hasSidewaysNeighbor(ETerritory eid) {
        for (ETerritory e : sidewaysNeighbors) {
            if (e == eid) {
                return true;
            }
        }
        return false;
    }

    public boolean hasActor(EActor aid) {
        for (Actor a : occupants) {
            if (a.who == aid) {
                return true;
            }
        }
        return false;
    }

    public boolean isAdjacentTo(ETerritory which) {
        for (ETerritory et : adjacent) {
            if (et == which) {
                return true;
            }
        }
        return false;
    }

    public boolean isOccupiedByDark() {
        return !occupants.isEmpty() && occupants.get(0).isDark();
    }

    public boolean isOccupiedByLight() {
        return !occupants.isEmpty() && occupants.get(0).isLight();
    }

    public boolean isOccupiedBy(Actor.Side side) {
        return !occupants.isEmpty() && occupants.get(0).side == side;
    }

    public Actor.Side occupyingSide() {
        if (occupants.isEmpty()) {
            return null;
        }
        return occupants.get(0).side;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(which.toString() + "[ ");
        for (Actor a : occupants) {
            sb.append(a.who + " ");
        }
        return sb.toString() + "]";
    }

    public static String nameFor(ETerritory et) {
        switch (et) {
            case SHIRE:
                return "The Shire";
            case ARTHEDAIN:
                return "Arthedain";
            case CARDOLAN:
                return "Cardolan";
            case RHUDAUR:
                return "Rhudaur";
            case EREGION:
                return "Eregion";
            case ENEDWAITH:
                return "Enedwaith";
            case HIGHPASS:
                return "The High Pass";
            case MISTYMTS:
                return "Misty Mountains";
            case MORIA:
                return "Moria";
            case GAPOFROHAN:
                return "Gap of Rohan";
            case MIRKWOOD:
                return "Mirkwood";
            case FANGORN:
                return "Fangorn";
            case ROHAN:
                return "Rohan";
            case DAGORLAD:
                return "Dagorlad";
            case GONDOR:
                return "Gondor";
            case MORDOR:
                return "Mordor";
            default:
                return null;
        }
    }

    public int getOccupantCount() {
        return occupants.size();
    }

    public void removeActor(Actor a) {
        occupants.remove(a);
        a.where = ETerritory.NOWHERE;
    }

    void clearOccupants() {
        for (Actor a: occupants) {
            a.where = ETerritory.NOWHERE;
        }
        occupants.clear();
    }
}
